// ==UserScript==
// @name        Invidious Instance Changer
// @namespace   cyberdevil.invidious.changer
// @include     https://*
// @version     0.0.2
// @downloadURL https://notabug.org/CYBERDEViL/userscripts/raw/master/invidious/cyberdevil.invidious.changer.user.js
// @updateURL   https://notabug.org/CYBERDEViL/userscripts/raw/master/invidious/cyberdevil.invidious.changer.user.js
// @grant       GM.setValue
// @grant       GM.getValue
// @grant       GM.xmlhttpRequest
// ==/UserScript==

// BETWEEN HERE and ..
if (GM_getValue('invidious.instances.isUpdating') === true) { return; }

const instancesStr = GM_getValue('invidious.instances');
if (!instancesStr){ // First time fetching instances list.
  updateInstances();
	return;
}

var instances = instancesStr.split(';');
if (instances.indexOf(window.location.host) < 0) { return; }
// .. BETWEEN HERE is run on every request, so keep it minimal.


var lastUpdated = GM_getValue('invidious.instances.lastUpdate');
var diffHours = (Date.now() - lastUpdated) / (1000 * 60 * 60);
//var diffMins = (Date.now() - lastUpdated) / (1000 * 60);

// Update instances
if (diffHours > 24) {
	updateInstances();
}

function updateInstances() {
	GM_setValue('invidious.instances.isUpdating', true);
	GM_xmlhttpRequest ({
		method: 'GET',
		url   : 'https://instances.invidio.us/instances.json',
		onload: function (request) {
			if(request.readyState == 4) {
				if(request.status == 200) {
					processJson(JSON.parse(request.responseText));
					saveInstances();
				}
				GM_setValue('invidious.instances.isUpdating', false);
			}
		}
	});
}

function processJson(json) {
	var newList = [];
	for (i in json) {
		if (json[i][1]['type'] != 'https') {
			continue;
		}
		if (!json[i][1]['monitor']) { 
			continue;
		}
		if( json[i][1]['monitor']['statusClass'] != 'success') {
			continue;
		}

		newList.push(json[i][1]['uri']);
		console.log(json[i][0]);
	}
	instances = newList;
}

function saveInstances() {
	var str = '';
	for (i in instances) {
		var url = new URL(instances[i]);
		str = str.concat(url.host).concat(";");
		console.log(url.host);
	}
	str = str.substr(0,str.length-1)
	console.log(str);
	GM_setValue('invidious.instances.lastUpdate', Date.now());
	GM_setValue('invidious.instances', str);
}

function getRandomInstance() {
	var newInstances = instances
	newInstances.splice (newInstances.indexOf(parsedUrl.host), 1); // remove current instance.
	var random = Math.floor(Math.random() * newInstances.length)
	return newInstances[Math.floor(Math.random() * newInstances.length)];
}

function generateRandomUrl(args) {
	return generateUrl(getRandomInstance(), args);
}

function generateUrl(host, args) {
	var url = "https://".concat(host.concat("/"));
	url = url.concat(args);
	return url;
}



// --- UI stuff
const parsedUrl = new URL(window.location);
// -- UI methods
function go() {
	// Change instance
	const args = parsedUrl.pathname.substr(1, parsedUrl.pathname.length).concat(parsedUrl.search);
	const url = generateUrl(instanceSelect.item(instanceSelect.selectedIndex).text, args);
	replaceUrl(url);
}

function random() {
	// Change to random instance
	const args = parsedUrl.pathname.substr(1, parsedUrl.pathname.length).concat(parsedUrl.search);
	const url = generateRandomUrl(args);
	replaceUrl(url);
}

function replaceUrl(url) {
	window.location.replace(url);
}


// -- UI elements
// - Main div
var mainDiv = document.createElement("div");
mainDiv.style.width = "200px"; 
mainDiv.style.position = "fixed";
mainDiv.style.top = 0;

// - Combobox
var instanceSelect = document.createElement("select");
for (i in instances) {
	if (instances[i] == parsedUrl.host) {
		// Skip current instance
		continue;
	}
	var option = document.createElement("option");
	option.text = instances[i];
	instanceSelect.add(option);
}

// - Go button
var goButton = document.createElement("input");
goButton.setAttribute("type", "button");
goButton.setAttribute("value", "Go");
goButton.addEventListener("click", go, false);

// - Random button
var randomButton = document.createElement("input");
randomButton.setAttribute("type", "button");
randomButton.setAttribute("value", "Random");
randomButton.addEventListener("click", random, false);

// - Add stuff
mainDiv.appendChild(instanceSelect);
mainDiv.appendChild(goButton);
mainDiv.appendChild(randomButton);
document.body.appendChild(mainDiv);
